import sys,os
__all__=['currentframe','find_caller','set_method']
def currentframe(back=None):
    if back is None:
        back=2
    assert(back>0)
    if hasattr(sys, '_getframe'):
        try:
            return sys._getframe(back)
        except ValueError:
            ret=sys._getframe()
            while ret.f_back is not None:
                ret=ret.f_back
            return ret
    else: #pragma: no cover
        """Return the frame object for the caller's stack frame."""

        try:
            raise Exception
        except Exception:
            return sys.exc_info()[back-1].tb_frame.f_back
from collections import namedtuple
CodeInfo=namedtuple('CodeInfo','file line func  module ')
this_dir=os.path.normcase(os.path.abspath(os.path.dirname(__file__)))
def find_caller(ignore=[]):
    f = currentframe()
    #On some versions of IronPython, currentframe() returns None if
    #IronPython isn't run with -X:Frames.
    ignore.append(this_dir) #this directory will always been ignore
    if f is not None:
        f = f.f_back

    rv = CodeInfo(None, 0, None,None)
    while hasattr(f, "f_code"):
        co = f.f_code
        filename = os.path.normcase(co.co_filename)
        if ignore is not None and filename in ignore:
            f = f.f_back
            continue
        rv = CodeInfo(co.co_filename, f.f_lineno, co.co_name,sys.modules[f.f_globals['__name__']])
        break
    return rv
def find_caller_frame(ignore=[]):
    f = currentframe()
    #On some versions of IronPython, currentframe() returns None if
    #IronPython isn't run with -X:Frames.
    ignore.append(this_dir) #this directory will always been ignore
    if f is not None:
        f = f.f_back

    rv = None
    while hasattr(f, "f_code"):
        co = f.f_code
        filename = os.path.normcase(co.co_filename)
        if ignore is not None and filename in ignore:
            f = f.f_back
            continue
        rv=f
        #~ print(f)
        break
    return rv
import types
def set_method(obj,name,func):
    setattr(obj,name, types.MethodType(func, obj))
